package com.thank.concurrency.samples.lock;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * description: 演示AQS中的Condition
 *
 * @author xiefayang
 * 2018/7/12 11:31
 */
@Slf4j
public class LockExample6 {

    public static void main(String[] args) {

        ReentrantLock lock = new ReentrantLock();
        // 从ReentrantLock实例中获取Condition
        Condition condition = lock.newCondition();


        new Thread(() -> {
            try {
                // Thread1调用lock方法, 于是被加入到AQS的等待队列中
                lock.lock();
                log.info("Thread1 wait signal~"); // 1

                // 调用await方法, 于是从AQS队列中移除, 加入到Condition队列中, 需要等待信号
                condition.await();
            } catch (InterruptedException e) {
                log.error("exception:", e);
            }

            log.info("Thread1 get signal~"); // 4
            lock.unlock();
        }).start();

        new Thread(() -> {
            // Thread1调用了await后, Thread2获取到了锁, 并加入到AQS队列中
            lock.lock();
            log.info("Thread2 get Lock~"); // 2
            try {
                Thread.sleep(3000);
            } catch (Exception e) {
                log.error("exception", e);
            }

            // 调用发送信号方法, Condition队列中的Thread1节点就被取出, 然后又放入AQS等待队列中(注意此时Thread1并未被唤醒?)
            condition.signalAll();
            log.info("Thread2 send signal~"); //3
            // Thread2释放锁, 此时AQS队列中只剩下Thread1了, 按照从头到尾的顺序唤醒线程, 此时Thread1被唤醒, 继续执行
            lock.unlock();
        }).start();


    }
}
